home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / libtiff / tif_write.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  18KB  |  578 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_write.c,v 1.51 93/03/30 21:52:20 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler
  7.  * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and 
  10.  * its documentation for any purpose is hereby granted without fee, provided
  11.  * that (i) the above copyright notices and this permission notice appear in
  12.  * all copies of the software and related documentation, and (ii) the names of
  13.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  14.  * publicity relating to the software without the specific, prior written
  15.  * permission of Sam Leffler and Silicon Graphics.
  16.  * 
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  18.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  19.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  20.  * 
  21.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  22.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  23.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  25.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  26.  * OF THIS SOFTWARE.
  27.  */
  28.  
  29. /*
  30.  * TIFF Library.
  31.  *
  32.  * Scanline-oriented Write Support
  33.  */
  34. #include "tiffiop.h"
  35. #include <assert.h>
  36. #include <stdio.h>
  37.  
  38. #define    STRIPINCR    20        /* expansion factor on strip array */
  39.  
  40. #if USE_PROTOTYPES
  41. static    int TIFFWriteCheck(TIFF *, int, const char*);
  42. static    int TIFFBufferSetup(TIFF *, const char*);
  43. static    int TIFFGrowStrips(TIFF *, int, const char*);
  44. static    int TIFFAppendToStrip(TIFF *, u_int, u_char *, u_long);
  45. static    int TIFFSetupStrips(TIFF *);
  46. #else
  47. static    int TIFFWriteCheck();
  48. static    int TIFFBufferSetup();
  49. static    int TIFFGrowStrips();
  50. static    int TIFFAppendToStrip();
  51. #endif
  52.  
  53. int
  54. /*VARARGS3*/
  55. DECLARE4(TIFFWriteScanline,
  56.     TIFF*, tif, u_char*, buf, u_int, row, u_int, sample)
  57. {
  58.     static const char module[] = "TIFFWriteScanline";
  59.     register TIFFDirectory *td;
  60.     int strip, status, imagegrew = 0;
  61.  
  62.     if (!TIFFWriteCheck(tif, 0, module))
  63.         return (-1);
  64.     /*
  65.      * Handle delayed allocation of data buffer.  This
  66.      * permits it to be sized more intelligently (using
  67.      * directory information).
  68.      */
  69.     if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) {
  70.         if (!TIFFBufferSetup(tif, module))
  71.             return (-1);
  72.         tif->tif_flags |= TIFF_BUFFERSETUP;
  73.     }
  74.     td = &tif->tif_dir;
  75.     /*
  76.      * Extend image length if needed
  77.      * (but only for PlanarConfig=1).
  78.      */
  79.     if (row >= td->td_imagelength) {    /* extend image */
  80.         if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
  81.             TIFFError(tif->tif_name,
  82.         "Can not change \"ImageLength\" when using separate planes");
  83.             return (-1);
  84.         }
  85.         td->td_imagelength = row+1;
  86.         imagegrew = 1;
  87.     }
  88.     /*
  89.      * Calculate strip and check for crossings.
  90.      */
  91.     if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
  92.         if (sample >= td->td_samplesperpixel) {
  93.             TIFFError(tif->tif_name,
  94.                 "%d: Sample out of range, max %d",
  95.                 sample, td->td_samplesperpixel);
  96.             return (-1);
  97.         }
  98.         strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip;
  99.     } else
  100.         strip = row / td->td_rowsperstrip;
  101.     if (strip != tif->tif_curstrip) {
  102.         /*
  103.          * Changing strips -- flush any data present.
  104.          */
  105.         if (!TIFFFlushData(tif))
  106.             return (-1);
  107.         tif->tif_curstrip = strip;
  108.         /*
  109.          * Watch out for a growing image.  The value of
  110.          * strips/image will initially be 1 (since it
  111.          * can't be deduced until the imagelength is known).
  112.          */
  113.         if (strip >= td->td_stripsperimage && imagegrew)
  114.             td->td_stripsperimage =
  115.                 howmany(td->td_imagelength, td->td_rowsperstrip);
  116.         tif->tif_row =
  117.             (strip % td->td_stripsperimage) * td->td_rowsperstrip;
  118.         if (tif->tif_preencode && !(*tif->tif_preencode)(tif))
  119.             return (-1);
  120.         tif->tif_flags |= TIFF_POSTENCODE;
  121.     }
  122.     /*
  123.      * Check strip array to make sure there's space.
  124.      * We don't support dynamically growing files that
  125.      * have data organized in separate bitplanes because
  126.      * it's too painful.  In that case we require that
  127.      * the imagelength be set properly before the first
  128.      * write (so that the strips array will be fully
  129.      * allocated above).
  130.      */
  131.     if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
  132.         return (-1);
  133.     /*
  134.      * Ensure the write is either sequential or at the
  135.      * beginning of a strip (or that we can randomly
  136.      * access the data -- i.e. no encoding).
  137.      */
  138.     if (row != tif->tif_row) {
  139.         if (tif->tif_seek) {
  140.             if (row < tif->tif_row) {
  141.                 /*
  142.                  * Moving backwards within the same strip:
  143.                  * backup to the start and then decode
  144.                  * forward (below).
  145.                  */
  146.                 tif->tif_row = (strip % td->td_stripsperimage) *
  147.                     td->td_rowsperstrip;
  148.                 tif->tif_rawcp = tif->tif_rawdata;
  149.             }
  150.             /*
  151.              * Seek forward to the desired row.
  152.              */
  153.             if (!(*tif->tif_seek)(tif, row - tif->tif_row))
  154.                 return (-1);
  155.             tif->tif_row = row;
  156.         } else {
  157.             TIFFError(tif->tif_name,
  158.             "Compression algorithm does not support random access");
  159.             return (-1);
  160.         }
  161.     }
  162.     status = (*tif->tif_encoderow)(tif, buf, tif->tif_scanlinesize, sample);
  163.     tif->tif_row++;
  164.     return (status);
  165. }
  166.  
  167. /*
  168.  * Encode the supplied data and write it to the
  169.  * specified strip.  There must be space for the
  170.  * data; we don't check if strips overlap!
  171.  *
  172.  * NB: Image length must be setup before writing; this
  173.  *     interface does not support automatically growing
  174.  *     the image on each write (as TIFFWriteScanline does).
  175.  */
  176. int
  177. DECLARE4(TIFFWriteEncodedStrip,
  178.     TIFF*, tif, u_int, strip, u_char*, data, u_long, cc)
  179. {
  180.     static const char module[] = "TIFFWriteEncodedStrip";
  181.     TIFFDirectory *td = &tif->tif_dir;
  182.  
  183.     if (!TIFFWriteCheck(tif, 0, module))
  184.         return (-1);
  185.     if (strip >= td->td_nstrips) {
  186.         TIFFError(module, "%s: Strip %d out of range, max %d",
  187.             tif->tif_name, strip, td->td_nstrips);
  188.         return (-1);
  189.     }
  190.     /*
  191.      * Handle delayed allocation of data buffer.  This
  192.      * permits it to be sized according to the directory
  193.      * info.
  194.      */
  195.     if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) {
  196.         if (!TIFFBufferSetup(tif, module))
  197.             return (-1);
  198.         tif->tif_flags |= TIFF_BUFFERSETUP;
  199.     }
  200.     tif->tif_curstrip = strip;
  201.     tif->tif_flags &= ~TIFF_POSTENCODE;
  202.     if (tif->tif_preencode && !(*tif->tif_preencode)(tif))
  203.         return (-1);
  204.     if (!(*tif->tif_encodestrip)(tif,
  205.         data, cc, strip / td->td_stripsperimage))
  206.         return (0);
  207.     if (tif->tif_postencode && !(*tif->tif_postencode)(tif))
  208.         return (-1);
  209.     if (td->td_fillorder != tif->tif_fillorder &&
  210.         (tif->tif_flags & TIFF_NOBITREV) == 0)
  211.         TIFFReverseBits((u_char *)tif->tif_rawdata, tif->tif_rawcc);
  212.     if (tif->tif_rawcc > 0 &&
  213.         !TIFFAppendToStrip(tif, strip, (u_char *)tif->tif_rawdata, tif->tif_rawcc))
  214.         return (-1);
  215.     tif->tif_rawcc = 0;
  216.     tif->tif_rawcp = tif->tif_rawdata;
  217.     return (cc);
  218. }
  219.  
  220. /*
  221.  * Write the supplied data to the specified strip.
  222.  * There must be space for the data; we don't check
  223.  * if strips overlap!
  224.  *
  225.  * NB: Image length must be setup before writing; this
  226.  *     interface does not support automatically growing
  227.  *     the image on each write (as TIFFWriteScanline does).
  228.  */
  229. int
  230. DECLARE4(TIFFWriteRawStrip,
  231.     TIFF*, tif, u_int, strip, u_char*, data, u_long, cc)
  232. {
  233.     static const char module[] = "TIFFWriteRawStrip";
  234.  
  235.     if (!TIFFWriteCheck(tif, 0, module))
  236.         return (-1);
  237.     if (strip >= tif->tif_dir.td_nstrips) {
  238.         TIFFError(module, "%s: Strip %d out of range, max %d",
  239.             tif->tif_name, strip, tif->tif_dir.td_nstrips);
  240.         return (-1);
  241.     }
  242.     return (TIFFAppendToStrip(tif, strip, data, cc) ? cc : -1);
  243. }
  244.  
  245. /*
  246.  * Write and compress a tile of data.  The
  247.  * tile is selected by the (x,y,z,s) coordinates.
  248.  */
  249. int
  250. DECLARE6(TIFFWriteTile,
  251.     TIFF*, tif, u_char*, buf, u_long, x, u_long, y, u_long, z, u_int, s)
  252. {
  253.     if (!TIFFCheckTile(tif, x, y, z, s))
  254.         return (-1);
  255.     /*
  256.      * NB: A tile size of -1 is used instead of tif_tilesize knowing
  257.      *     that TIFFWriteEncodedTile will clamp this to the tile size.
  258.      *     This is done because the tile size may not be defined until
  259.      *     after the output buffer is setup in TIFFBufferSetup.
  260.      */
  261.     return (TIFFWriteEncodedTile(tif,
  262.         TIFFComputeTile(tif, x, y, z, s), buf, (u_int)-1));
  263. }
  264.  
  265. /*
  266.  * Encode the supplied data and write it to the
  267.  * specified tile.  There must be space for the
  268.  * data.  The function clamps individual writes
  269.  * to a tile to the tile size, but does not (and
  270.  * can not) check that multiple writes to the same
  271.  * tile do not write more than tile size data.
  272.  *
  273.  * NB: Image length must be setup before writing; this
  274.  *     interface does not support automatically growing
  275.  *     the image on each write (as TIFFWriteScanline does).
  276.  */
  277. int
  278. DECLARE4(TIFFWriteEncodedTile,
  279.     TIFF*, tif, u_int, tile, u_char*, data, u_long, cc)
  280. {
  281.     static const char module[] = "TIFFWriteEncodedTile";
  282.     TIFFDirectory *td;
  283.  
  284.     if (!TIFFWriteCheck(tif, 1, module))
  285.         return (-1);
  286.     td = &tif->tif_dir;
  287.     if (tile >= td->td_nstrips) {
  288.         TIFFError(module, "%s: Tile %d out of range, max %d",
  289.             tif->tif_name, tile, td->td_nstrips);
  290.         return (-1);
  291.     }
  292.     /*
  293.      * Handle delayed allocation of data buffer.  This
  294.      * permits it to be sized more intelligently (using
  295.      * directory information).
  296.      */
  297.     if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) {
  298.         if (!TIFFBufferSetup(tif, module))
  299.             return (-1);
  300.         tif->tif_flags |= TIFF_BUFFERSETUP;
  301.     }
  302.     tif->tif_curtile = tile;
  303.     /* 
  304.      * Compute tiles per row & per column to compute
  305.      * current row and column
  306.      */
  307.     tif->tif_row = (tile % howmany(td->td_imagelength, td->td_tilelength))
  308.         * td->td_tilelength;
  309.     tif->tif_col = (tile % howmany(td->td_imagewidth, td->td_tilewidth))
  310.         * td->td_tilewidth;
  311.  
  312.     tif->tif_flags &= ~TIFF_POSTENCODE;
  313.     if (tif->tif_preencode && !(*tif->tif_preencode)(tif))
  314.         return (-1);
  315.     /*
  316.      * Clamp write amount to the tile size.  This is mostly
  317.      * done so that callers can pass in some large number
  318.      * (e.g. -1) and have the tile size used instead.
  319.      */
  320.     if (cc > tif->tif_tilesize)
  321.         cc = tif->tif_tilesize;
  322.     if (!(*tif->tif_encodetile)(tif, data, cc, tile/td->td_stripsperimage))
  323.         return (0);
  324.     if (tif->tif_postencode && !(*tif->tif_postencode)(tif))
  325.         return (-1);
  326.     if (td->td_fillorder != tif->tif_fillorder &&
  327.         (tif->tif_flags & TIFF_NOBITREV) == 0)
  328.         TIFFReverseBits((u_char *)tif->tif_rawdata, tif->tif_rawcc);
  329.     if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
  330.         (u_char *)tif->tif_rawdata, tif->tif_rawcc))
  331.         return (-1);
  332.     tif->tif_rawcc = 0;
  333.     tif->tif_rawcp = tif->tif_rawdata;
  334.     return (cc);
  335. }
  336.  
  337. /*
  338.  * Write the supplied data to the specified strip.
  339.  * There must be space for the data; we don't check
  340.  * if strips overlap!
  341.  *
  342.  * NB: Image length must be setup before writing; this
  343.  *     interface does not support automatically growing
  344.  *     the image on each write (as TIFFWriteScanline does).
  345.  */
  346. int
  347. DECLARE4(TIFFWriteRawTile,
  348.     TIFF*, tif, u_int, tile, u_char*, data, u_long, cc)
  349. {
  350.     static const char module[] = "TIFFWriteRawTile";
  351.  
  352.     if (!TIFFWriteCheck(tif, 1, module))
  353.         return (-1);
  354.     if (tile >= tif->tif_dir.td_nstrips) {
  355.         TIFFError(module, "%s: Tile %d out of range, max %d",
  356.             tif->tif_name, tile, tif->tif_dir.td_nstrips);
  357.         return (-1);
  358.     }
  359.     return (TIFFAppendToStrip(tif, tile, data, cc) ? cc : -1);
  360. }
  361.  
  362. static int
  363. DECLARE1(TIFFSetupStrips, TIFF*, tif)
  364. {
  365. #define    isUnspecified(td, v) \
  366.     (td->v == 0xffffffff || (td)->td_imagelength == 0)
  367.     register TIFFDirectory *td = &tif->tif_dir;
  368.  
  369.     if (!isTiled(tif))
  370.         td->td_stripsperimage = isUnspecified(td, td_rowsperstrip) ?
  371.             1 : howmany(td->td_imagelength, td->td_rowsperstrip);
  372.     else
  373.         td->td_stripsperimage = isUnspecified(td, td_tilelength) ?
  374.             1 : TIFFNumberOfTiles(tif);
  375.     td->td_nstrips = td->td_stripsperimage;
  376.     if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
  377.         td->td_nstrips *= td->td_samplesperpixel;
  378.     td->td_stripoffset = (u_long *)
  379.         _TIFFmalloc(td->td_nstrips * sizeof (u_long));
  380.     td->td_stripbytecount = (u_long *)
  381.         _TIFFmalloc(td->td_nstrips * sizeof (u_long));
  382.     if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
  383.         return (0);
  384.     /*
  385.      * Place data at the end-of-file
  386.      * (by setting offsets to zero).
  387.      */
  388.     memset(td->td_stripoffset, 0, td->td_nstrips*sizeof (u_long));
  389.     memset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (u_long));
  390.     TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
  391.     TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
  392.     return (1);
  393. #undef isUnspecified
  394. }
  395.  
  396. /*
  397.  * Verify file is writable and that the directory
  398.  * information is setup properly.  In doing the latter
  399.  * we also "freeze" the state of the directory so
  400.  * that important information is not changed.
  401.  */
  402. static int
  403. DECLARE3(TIFFWriteCheck, TIFF*, tif, int, tiles, const char*, module)
  404. {
  405.     if (tif->tif_mode == O_RDONLY) {
  406.         TIFFError(module, "%s: File not open for writing",
  407.             tif->tif_name);
  408.         return (0);
  409.     }
  410.     if (tiles ^ isTiled(tif)) {
  411.         TIFFError(tif->tif_name, tiles ?
  412.             "Can not write tiles to a stripped image" :
  413.             "Can not write scanlines to a tiled image");
  414.         return (0);
  415.     }
  416.     /*
  417.      * On the first write verify all the required information
  418.      * has been setup and initialize any data structures that
  419.      * had to wait until directory information was set.
  420.      * Note that a lot of our work is assumed to remain valid
  421.      * because we disallow any of the important parameters
  422.      * from changing after we start writing (i.e. once
  423.      * TIFF_BEENWRITING is set, TIFFSetField will only allow
  424.      * the image's length to be changed).
  425.      */
  426.     if ((tif->tif_flags & TIFF_BEENWRITING) == 0) {
  427.         if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
  428.             TIFFError(module,
  429.                 "%s: Must set \"ImageWidth\" before writing data",
  430.                 tif->tif_name);
  431.             return (0);
  432.         }
  433.         if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
  434.             TIFFError(module,
  435.             "%s: Must set \"PlanarConfiguration\" before writing data",
  436.                 tif->tif_name);
  437.             return (0);
  438.         }
  439.         if (tif->tif_dir.td_stripoffset == NULL &&
  440.             !TIFFSetupStrips(tif)) {
  441.             tif->tif_dir.td_nstrips = 0;
  442.             TIFFError(module, "%s: No space for %s arrays",
  443.                 tif->tif_name, isTiled(tif) ? "tile" : "strip");
  444.             return (0);
  445.         }
  446.         tif->tif_flags |= TIFF_BEENWRITING;
  447.     }
  448.     return (1);
  449. }
  450.  
  451. /*
  452.  * Setup the raw data buffer used for encoding.
  453.  */
  454. static int
  455. DECLARE2(TIFFBufferSetup, TIFF*, tif, const char*, module)
  456. {
  457.     u_long size;
  458.  
  459.     if (isTiled(tif))
  460.         tif->tif_tilesize = size = TIFFTileSize(tif);
  461.     else
  462.         tif->tif_scanlinesize = size = TIFFScanlineSize(tif);
  463.     /*
  464.      * Make raw data buffer at least 8K
  465.      */
  466.     if (size < 8*1024)
  467.         size = 8*1024;
  468.     tif->tif_rawdata = _TIFFmalloc(size);
  469.     if (tif->tif_rawdata == NULL) {
  470.         TIFFError(module, "%s: No space for output buffer",
  471.             tif->tif_name);
  472.         return (0);
  473.     }
  474.     tif->tif_flags |= TIFF_MYBUFFER;
  475.     tif->tif_rawdatasize = size;
  476.     tif->tif_rawcc = 0;
  477.     tif->tif_rawcp = tif->tif_rawdata;
  478.     return (1);
  479. }
  480.  
  481. /*
  482.  * Grow the strip data structures by delta strips.
  483.  */
  484. static int
  485. DECLARE3(TIFFGrowStrips, TIFF*, tif, int, delta, const char*, module)
  486. {
  487.     TIFFDirectory *td = &tif->tif_dir;
  488.  
  489.     assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
  490.     td->td_stripoffset = (u_long *)_TIFFrealloc(td->td_stripoffset,
  491.         (td->td_nstrips + delta) * sizeof (u_long));
  492.     td->td_stripbytecount = (u_long *)_TIFFrealloc(td->td_stripbytecount,
  493.         (td->td_nstrips + delta) * sizeof (u_long));
  494.     if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) {
  495.         td->td_nstrips = 0;
  496.         TIFFError(module, "%s: No space to expand strip arrays",
  497.             tif->tif_name);
  498.         return (0);
  499.     }
  500.     memset(td->td_stripoffset+td->td_nstrips, 0, delta*sizeof (u_long));
  501.     memset(td->td_stripbytecount+td->td_nstrips, 0, delta*sizeof (u_long));
  502.     td->td_nstrips += delta;
  503.     return (1);
  504. }
  505.  
  506. /*
  507.  * Append the data to the specified strip.
  508.  *
  509.  * NB: We don't check that there's space in the
  510.  *     file (i.e. that strips do not overlap).
  511.  */
  512. static int
  513. DECLARE4(TIFFAppendToStrip, TIFF*, tif, u_int, strip, u_char*, data, u_long, cc)
  514. {
  515.     TIFFDirectory *td = &tif->tif_dir;
  516.     static const char module[] = "TIFFAppendToStrip";
  517.  
  518.     if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
  519.         /*
  520.          * No current offset, set the current strip.
  521.          */
  522.         if (td->td_stripoffset[strip] != 0) {
  523.             if (!SeekOK(tif, td->td_stripoffset[strip])) {
  524.                 TIFFError(module,
  525.                     "%s: Seek error at scanline %d",
  526.                     tif->tif_name, tif->tif_row);
  527.                 return (0);
  528.             }
  529.         } else
  530.             td->td_stripoffset[strip] =
  531.                 TIFFSeekFile(tif, 0L, L_XTND);
  532.         tif->tif_curoff = td->td_stripoffset[strip];
  533.     }
  534.     if (!WriteOK(tif, data, cc)) {
  535.         TIFFError(module, "%s: Write error at scanline %d",
  536.             tif->tif_name, tif->tif_row);
  537.         return (0);
  538.     }
  539.     tif->tif_curoff += cc;
  540.     td->td_stripbytecount[strip] += cc;
  541.     return (1);
  542. }
  543.  
  544. /*
  545.  * Internal version of TIFFFlushData that can be
  546.  * called by ``encodestrip routines'' w/o concern
  547.  * for infinite recursion.
  548.  */
  549. int
  550. DECLARE1(TIFFFlushData1, TIFF*, tif)
  551. {
  552.     if (tif->tif_rawcc > 0) {
  553.         if (tif->tif_dir.td_fillorder != tif->tif_fillorder &&
  554.             (tif->tif_flags & TIFF_NOBITREV) == 0)
  555.             TIFFReverseBits((u_char *)tif->tif_rawdata,
  556.                 tif->tif_rawcc);
  557.         if (!TIFFAppendToStrip(tif,
  558.             isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
  559.             (u_char *)tif->tif_rawdata, tif->tif_rawcc))
  560.             return (0);
  561.         tif->tif_rawcc = 0;
  562.         tif->tif_rawcp = tif->tif_rawdata;
  563.     }
  564.     return (1);
  565. }
  566.  
  567. /*
  568.  * Set the current write offset.  This should only be
  569.  * used to set the offset to a known previous location
  570.  * (very carefully), or to 0 so that the next write gets
  571.  * appended to the end of the file.
  572.  */
  573. void
  574. DECLARE2(TIFFSetWriteOffset, TIFF*, tif, u_long, off)
  575. {
  576.     tif->tif_curoff = off;
  577. }
  578.